import _ from 'lodash';
import axios from 'axios';
import chain from './chain.js';
import { Balance, Coin } from '@/types/tokens.js';

// 从chrome的runtime中获取manifest数据，这通常包含扩展的基本信息、权限等
let manifestData = chrome.runtime.getManifest();

// 定义了一个对象lightApis，包含了各种区块链的轻量级API地址

//https://wax.greymass.com/v1

const lightApis = {
    mos: 'http://13.212.121.102:8888',
    wax: 'https://wax.light-api.net',
    telos: 'https://telos.light-api.net',
    proton: 'https://proton.light-api.net',
    kylin: 'https://testnet-lightapi.eosams.xeos.me',
    'telos-test': 'https://testnet-lightapi.eosams.xeos.me',
    'wax-test': 'https://testnet-lightapi.eosams.xeos.me',
    'proton-test': 'https://testnet-lightapi.eosams.xeos.me',
};


// 定义了一个对象hyperionApis，包含了各种区块链的API地址
const hyperionApis = {
    mos: 'http://13.212.121.102:8888', //https://api.eossweden.org/v2
    bos: 'https://api.bossweden.org',
    wax: 'https://wax.eosrio.io',
    telos: 'https://telos.eosrio.io', // https://mainnet.telos.net/v2
    proton: 'https://proton.cryptolions.io',
    kylin: 'https://kylin.eossweden.org',
    jungle: 'https://jungle.eossweden.org',
    jungle3: 'https://jungle3.eosrio.io',
    'bos-test': 'https://tst.bossweden.org',
    'telos-test': 'https://testnet.telos.net',
    'wax-test': 'https://testnet.wax.pink.gg',
    'proton-test': 'https://testnet.protonchain.com',
};

// 定义一个类型lightKey，包含了lightApis对象中定义的键
export type lightKey =
    | 'mos'
    | 'wax'
    | 'telos'
    | 'proton'
    | 'kylin'
    | 'telos-test'
    | 'wax-test'
    | 'proton-test';

// 定义一个类型hyperionKey，包含了hyperionApis对象中定义的键
type hyperionKey =
    | 'mos'
    | 'bos'
    | 'wax'
    | 'telos'
    | 'proton'
    | 'kylin'
    | 'jungle'
    | 'jungle3'
    | 'bos-test'
    | 'telos-test'
    | 'wax-test'
    | 'proton-test';


// 定义一个函数 isSupportChain，它接受一个字符串chain作为参数，并检查这个chain在hyperionApis对象中是否存在
// 如果存在，则返回true，否则返回false
export const isSupportChain = (chain: string) => {
    return hyperionApis[chain as hyperionKey] ? true : false;
};

// 定义一个异步函数 getEndpoints，用于获取指定区块链的RPC端点列表
// 参数：
//   - chainId: 默认为当前链的ID，通过useChainStore().currentChainId获取
export const getEndpoints = async (chainId = useChainStore().currentChainId) => {
    try {
        // 通过useChainStore().findNetwork(chainId)找到与chainId对应的网络配置
        // 然后获取该网络的chain属性，即区块链的名称或标识
        const chain = useChainStore().findNetwork(chainId).chain;

        // 构造请求的URL，通过CDN从GitHub上加载特定区块链的RPC端点配置文件
        // 这里的URL模板是固定的，只是根据chain的值动态替换文件路径
        let res = await axios.get(
            `https://cdn.jsdelivr.net/gh/metahubwallet/chain-rpcs@master/${chain}-rpcs.json`
        );

        // 如果请求成功，返回RPC端点配置数据
        // 如果请求失败或返回的数据无效，返回空数组
        return res ? res.data : [];
    } catch (e) {
        // 如果在请求或处理过程中发生错误，捕获错误
        // 返回空数组表示获取RPC端点列表失败
        return [];
    }
};

// 定义一个异步函数 getKeyAccounts，它接收两个参数：chain（链的标识符，值为lightKey的某一个值）和publicKey（公钥字符串）
export const getKeyAccounts = async (chain: lightKey, publicKey: string) => {
    try {
        // 检查传入的chain在lightApis对象中是否存在API地址
        if (!lightApis[chain]) return []; // 如果不存在，则直接返回一个空数组

        // 修改publicKey的格式，给公钥添加一个前缀"M"
        publicKey = "M" + publicKey.substring(1);

        // 拼接API地址，用于获取与公钥关联的账户名列表
        let url = lightApis[chain] + "/v1/history/get_key_accounts";

        // 使用axios发送POST请求到上述拼接的url地址
        let res = await axios.post(url, '{"public_key":"' + publicKey + '"}');

        // 检查请求是否成功（状态码为200）并且返回了数据
        if (res.status == 200 && res.data) {
            // 定义一个常量ckey，这里直接赋值为"account_names"，用于后续从响应数据中提取账户名列表
            const ckey = "account_names";

            // 检查返回的账户名列表是否有内容
            if (res.data.account_names.length > 0) {
                // 返回与公钥关联的账户名列表
                return res.data.account_names;
            }
        }
    } catch (e) {
        // 如果在请求过程中发生任何错误，捕获这个错误并在控制台打印出来
        console.error(e);
    }
    // 如果请求失败或没有找到任何账户名，则返回空数组
    return [];
};

// 定义一个异步函数 getBalanceList，用于获取指定账户的代币余额列表
// 参数：
//   - account: string，账户地址
//   - tokens: Coin[]，代币数组
//   - onBlanceInquired: Function，当每个余额查询完成时调用的回调函数
export const getBalanceList = async (
    account: string,
    tokens: Coin[],
    onBlanceInquired: Function
) => {
    try {
        // to use: http://light-api/api/account/CHAIN/ACCOUNT
        // 创建一个空数组，用于存储查询到的余额信息
        const balances = [] as Balance[];

        // 遍历传入的代币数组
        for (const t of tokens) {
            // 调用链的API方法，获取指定代币在指定账户的余额
            const balance = await chain.getApi().getCurrencyBalance(t.contract, account, t.symbol);

            // 提取余额数值，如果获取失败则默认为0
            const amount = balance ? parseFloat(balance.split(' ')[0]) : 0;

            // 创建一个新的Balance对象，包含代币信息和余额数值
            const item: Balance = { ...t, amount };

            // 将新的Balance对象添加到balances数组中
            balances.push(item);

            // 如果传入了onBlanceInquired回调函数，并且它是一个函数类型，则调用该回调函数，传入当前的余额信息
            if (typeof onBlanceInquired == 'function') {
                onBlanceInquired(item);
            }
        }
        console.log(345,balances)
        // 返回查询到的余额列表
        return balances;
    } catch (e) {
        // 如果在查询余额过程中发生错误，捕获错误并在控制台打印出来
        console.error(e);

        // 返回空数组表示查询失败
        return [];
    }
};

// 定义一个异步函数 getBpInfo，用于获取区块链节点（BP，Block Producer）信息
export const getBpInfo = async () => {
    // 返回一个对象，包含 data（数据）、code（状态码）和 msg（消息）三个字段
    // 在这里，data 是一个空数组，表示尚未获取到任何BP信息
    // code 设置为 1，通常表示请求成功或信息获取正常（具体含义可能根据业务逻辑有所不同）
    // msg 为空字符串，表示没有额外的消息或错误信息
    return { data: [], code: 1, msg: '' };
};

// 定义一个异步函数 getTransactionList，用于获取指定账户的交易列表
// 参数：
//   - chain: string，区块链的名称或标识
//   - data: any，查询交易列表时所需的账户名或其他相关数据
export const getTransactionList = async (chain: string, data: any) => {
    try {
        // 检查传入的链名是否在hyperionApis对象中，如果不存在则返回空数组
        if (!hyperionApis[chain as hyperionKey]) return [];

        // 构造API请求URL，用于获取交易列表
        // 这里的URL是硬编码的，实际应用中可能需要根据chain参数动态构建
        let url = "http://13.212.121.102:55500/Explorer/Transaction/ListOfAccount?page=1&accountName="+data;

        // 使用axios发起GET请求，获取交易列表数据
        let res = await axios.get(url);

        // 如果请求成功，则获取响应数据，否则返回空数组
        const actions = res ? res.data : [];

        // 遍历响应数据中的actions数组
        for(let i=0;i<actions.data.length;i++) {
            // 重新命名字段，以便后续使用
            // trx_id: 交易ID
            actions.data[i].trx_id = actions.data[i].transactionId;
            // block_num: 区块号
            actions.data[i].block_num = actions.data[i].blockNum;
            // receiver: 接收者地址
            actions.data[i].receiver = actions.data[i].actData.to;
            // sender: 发送者地址
            actions.data[i].sender = actions.data[i].actData.from;
            // quantity: 交易数量
            actions.data[i].quantity = actions.data[i].actData.quantity;
            // memo: 交易备注
            actions.data[i].memo = actions.data[i].actData.memo;
        }
        // 返回处理后的交易列表数据
        return actions.data;
    } catch (e) {
        // 如果在请求或处理过程中发生错误，捕获错误并在控制台打印出来
        console.error(e);
        // 返回空数组表示请求失败或处理出错
        return [];
    }
};
